<?php

namespace app\admin\controller\food;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use app\common\controller\Backend;
use think\db;
/**
 * 食物成分管理
 *
 * @icon fa fa-circle-o
 */
class Ingredient extends Backend
{

    /**
     * Ingredient模型对象
     * @var \app\admin\model\food\Ingredient
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\food\Ingredient;
        $this->view->assign("statusList", $this->model->getStatusList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */


    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $list = $this->model
                    ->with(['categories'])
                    ->where($where)
                    ->order($sort, $order)
                    ->paginate($limit);

            foreach ($list as $row) {
                $row->visible(['id','name','categories_id','smallimage','weight','edible_portion','water_content','energy_kilocalorie','energy_kj','protein','fat','createtime','status','weigh']);
                $row->visible(['categories']);
				$row->getRelation('categories')->visible(['name']);
            }

            $result = array("total" => $list->total(), "rows" => $list->items());

            return json($result);
        }
        return $this->view->fetch();
    }
    
    /**
     * 导入
     */
    public function import()
    {
        parent::import();
    }
    
    /**
     * 自动为未分类食材补充分类（调用阿里云千问API）
     */
    public function autoClassify()
    {
        // 1. 步骤1：提取未分类的食材（每次取10条，避免API请求过载，可调整）
        $ingredients = $this->getUnclassifiedIngredients(100);
        if (empty($ingredients)) {
            return json(['code' => 0, 'msg' => '暂无未分类食材']);
        }

        // 2. 步骤2-4：循环处理每个食材
        $successCount = 0;
        $failList = [];
        foreach ($ingredients as $ing) {
            $ingId = $ing['id'];
            $ingName = $ing['name'];

            // 2.1 调用千问API查询分类
            $categoryInfo = $this->queryCategoryByQwen($ingName);
            if (empty($categoryInfo) || !isset($categoryInfo['parent_name'], $categoryInfo['child_name'])) {
                $failList[] = "食材【{$ingName}】（ID:{$ingId}）：API未返回有效分类";
                // 标记为已调用AI，避免重复调用无效的API请求
                $this->markAiCalled($ingId);
                continue;
            }

            // 2.2 匹配分类表的ID和parent_id
            $categoryIds = $this->matchCategoryIds(
                $categoryInfo['parent_name'],
                $categoryInfo['child_name']
            );
            if (empty($categoryIds)) {
                $failList[] = "食材【{$ingName}】（ID:{$ingId}）：未匹配到分类表记录";
                // 标记为已调用AI，避免重复调用无效的API请求
                $this->markAiCalled($ingId);
                continue;
            }

            // 2.3 更新食材表
            $updateRes = $this->updateIngredientCategory(
                $ingId,
                $categoryIds['parent_id'],
                $categoryIds['categories_id']
            );
            if ($updateRes) {
                $successCount++;
                // 标记为已调用AI
                $this->markAiCalled($ingId);
            } else {
                $failList[] = "食材【{$ingName}】（ID:{$ingId}）：更新数据库失败";
            }
        }

        // 3. 返回结果
        $result = [
            'code' => 1,
            'msg' => "处理完成，成功{$successCount}条，失败" . count($failList) . "条",
            'data' => [
                'success_count' => $successCount,
                'fail_list' => $failList
            ]
        ];
        return json($result);
    }
    
    /**
     * 获取未分类的食材
     * @param int $limit 每次获取的数量（避免一次性处理过多）
     * @return array
     */
    private function getUnclassifiedIngredients($limit = 10)
    {
        // 使用新的模型并修改查询条件，同时检查null和空字符串
        // 添加ai_called条件，只获取未调用过AI的食材
        $result = \app\common\model\FoodIngredient::where(function($query) {
            $query->where('parent_id', null)
                  ->where('categories_id', null);
        })->whereOr(function($query) {
            $query->where('parent_id', '')
                  ->where('categories_id', '');
        })->where('ai_called', 0) // 只获取未调用过AI的食材
        ->field('id, name')->limit($limit)->select();
        // 确保正确转换为数组
        return $result ? json_decode(json_encode($result), true) : [];
    }
    
    /**
     * 标记食材已调用AI
     * @param int $ingId 食材ID
     */
    private function markAiCalled($ingId)
    {
        try {
            \app\common\model\FoodIngredient::where('id', $ingId)->update([
                'ai_called' => 1,
                'updatetime' => time()
            ]);
        } catch (\Exception $e) {
            trace("标记食材AI调用状态失败：{$e->getMessage()}", 'error');
        }
    }
    
    /**
     * 调用阿里云千问API查询食材分类
     * @param string $ingName 食材名称（如"丁香"）
     * @return array|null 结构化结果：['parent_name' => '调味品', 'child_name' => '香辛料']
     */
    private function queryCategoryByQwen($ingName)
    {
        // 获取现有的分类数据
        $categories = $this->getExistingCategories();
        
        // 1. 构造API请求参数（核心：明确提示词，让返回格式标准化）
        $prompt = <<<PROMPT
        请将食材【{$ingName}】归类到以下已有的分类结构中，遵循以下规则：
        1. 请从下面提供的一级分类和二级分类中选择最匹配的分类；
        2. 如果找不到合适的分类，请返回"未知-未知"；
        3. 仅返回结果，格式严格为：一级分类名称,二级分类名称（不要任何多余文字）。

        现有分类结构：
        {$categories}

        示例：
        输入：丁香 → 输出：调味品,香辛料
        输入：苹果 → 输出：水果类及制品,仁果类
        输入：八角 → 输出：调味品,香辛料
        PROMPT;
        $data = [
            'model' => 'qwen-plus', // 使用配置中的默认模型
            'messages' => [
                [
                    'role' => 'user',
                    'content' => $prompt
                ]
            ],
            'temperature' => 0.1, // 温度越低，结果越稳定（避免随机性）
            'max_tokens' => 100 // 限制返回长度，够用即可
        ];

        // 2. 调用你已有的API函数
        $response = $this->getCompletions($data);
        $responseArr = json_decode($response, true);
        // 3. 解析API返回结果
        if (empty($responseArr['choices'][0]['message']['content'])) {
            return null;
        }
        $content = trim($responseArr['choices'][0]['message']['content']);
        
        // 4. 按格式拆分父/子分类（如"调味品,香辛料"拆分为数组）
        list($parentName, $childName) = explode(',', $content) + [1 => '未知'];
        if ($parentName === '未知' && $childName === '未知') {
            return null;
        }

        return [
            'parent_name' => trim($parentName),
            'child_name' => trim($childName)
        ];
    }
    
    /**
     * 获取现有的分类数据
     * @return string 格式化后的分类数据
     */
    private function getExistingCategories()
    {
        // 获取所有一级分类
        $parentCategories = \app\common\model\FoodCategories::where('parent_id', 0)
            ->field('id, name')
            ->select();
        
        // 确保正确转换为数组
        $parentCategories = $parentCategories ? json_decode(json_encode($parentCategories), true) : [];
        
        $categoryText = '';
        foreach ($parentCategories as $parent) {
            $categoryText .= "一级分类：{$parent['name']}\n";
            
            // 获取对应的二级分类
            $childCategories = \app\common\model\FoodCategories::where('parent_id', $parent['id'])
                ->field('name')
                ->select();
            
            // 确保正确转换为数组
            $childCategories = $childCategories ? json_decode(json_encode($childCategories), true) : [];
            
            if (!empty($childCategories)) {
                $childNames = array_column($childCategories, 'name');
                $categoryText .= "  二级分类：" . implode('、', $childNames) . "\n";
            }
            $categoryText .= "\n";
        }
        
        return $categoryText;
    }
    
    /**
     * 根据父/子分类名称匹配分类表的parent_id和categories_id
     * @param string $parentName 父分类名称（如"调味品"）
     * @param string $childName 子分类名称（如"香辛料"）
     * @return array|null ['parent_id' => 107, 'categories_id' => 113]
     */
    private function matchCategoryIds($parentName, $childName)
    {
        // 1. 先查子分类（核心：子分类的id是categories_id，其parent_id是食材表的parent_id）
        // 使用新的模型
        $childCategory = \app\common\model\FoodCategories::where('name', 'like', "%{$childName}%")
            ->field('id, parent_id')
            ->find();

        if (!empty($childCategory)) {
            // 子分类存在，直接返回（无需校验父分类，避免名称差异）
            return [
                'parent_id' => $childCategory['parent_id'],
                'categories_id' => $childCategory['id']
            ];
        }

        // 2. 若子分类未匹配到，尝试通过父分类模糊匹配（降级处理）
        $parentCategory = \app\common\model\FoodCategories::where('name', 'like', "%{$parentName}%")
            ->field('id')
            ->find();
        if (!empty($parentCategory)) {
            // 仅能匹配到父分类，子分类留空（后续手动处理）
            return [
                'parent_id' => $parentCategory['id'],
                'categories_id' => null
            ];
        }

        return null;
    }
    
    /**
     * 更新食材的分类信息
     * @param int $ingId 食材ID
     * @param int $parentId 父分类ID（对应fa_food_categories.parent_id）
     * @param int|null $categoriesId 子分类ID（对应fa_food_categories.id）
     * @return bool
     */
    private function updateIngredientCategory($ingId, $parentId, $categoriesId = null)
    {
        try {
            // 使用新的模型
            \app\common\model\FoodIngredient::where('id', $ingId)->update([
                'parent_id' => $parentId,
                'categories_id' => $categoriesId,
                'updatetime' => time() // 记录更新时间
            ]);
            return true;
        } catch (\Exception $e) {
            // 记录错误日志（FastAdmin默认日志功能）
            trace("更新食材分类失败：{$e->getMessage()}", 'error');
            return false;
        }
    }
    
    /**
     * 调用阿里云千问API
     * @param array $data 请求数据
     * @return string API响应
     */
    private function getCompletions($data)
    {
        
        // 这里需要根据实际的阿里云千问API配置来实现
        // 示例代码，需要根据实际情况调整
        $apiKey = 'sk-416b931b781c420c9f6331b7346962b5'; // 从配置中获取API密钥
        $apiUrl = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions'; // 从配置中获取API地址
        // 如果配置不存在，则返回空结果
        if (empty($apiKey) || empty($apiUrl)) {
            return json_encode(['choices' => [['message' => ['content' => '']]]]);
        }
        
        // 发起HTTP请求
        $headers = [
            'Authorization: Bearer ' . $apiKey,
            'Content-Type: application/json',
            'X-DashScope-SSE: enable'
        ];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过SSL验证，生产环境中应正确配置
        
        $response = curl_exec($ch);
        
        // 检查是否有错误
        if (curl_errno($ch)) {
            trace('千问API调用错误: ' . curl_error($ch), 'error');
            curl_close($ch);
            return json_encode(['choices' => [['message' => ['content' => '']]]]);
        }
        
        curl_close($ch);
        
        return $response;
    }

}